import os
import re
import subprocess
from pathlib import Path
from typing import Optional, Dict, Union

class BaseOSDetector:
    """操作系统检测基类，插件开发者需继承此类并实现 detect() 方法"""
    
    def detect(self) -> bool:
        """
        检测当前系统是否匹配目标发行版
        返回值: bool - 如果匹配返回 True，否则 False
        """
        raise NotImplementedError("子类必须实现此方法")

    # --------------- 通用工具方法 (供子类调用) ---------------
    @staticmethod
    def get_os_release() -> Dict[str, str]:
        """
        解析 /etc/os-release 或 /usr/lib/os-release 文件
        返回: 包含系统信息的字典，例如 {'ID': 'ubuntu', 'VERSION_ID': '22.04'}
        """
        os_release_paths = [
            Path("/etc/os-release"),
            Path("/usr/lib/os-release")
        ]
        
        os_info = {}
        for path in os_release_paths:
            if path.exists():
                with open(path, "r") as f:
                    for line in f:
                        line = line.strip()
                        if line and "=" in line and not line.startswith("#"):
                            key, value = line.split("=", 1)
                            os_info[key] = value.strip('"')
                break
        return os_info

    @staticmethod
    def check_file_exists(file_pattern: Union[str, list]) -> bool:
        """
        检查文件或文件列表是否存在
        参数: 
            file_pattern - 可以是单个路径字符串，或路径列表
        示例: 
            check_file_exists("/etc/redhat-release")  
            check_file_exists(["/etc/arch-release", "/etc/arch_linux"])
        """
        if isinstance(file_pattern, str):
            return Path(file_pattern).exists()
        elif isinstance(file_pattern, list):
            return any(Path(f).exists() for f in file_pattern)
        return False

    @staticmethod
    def exec_command(cmd: str) -> Optional[str]:
        """
        执行 Shell 命令并返回输出 (忽略错误)
        参数: cmd - 要执行的命令
        返回: 命令输出文本 (失败返回 None)
        """
        try:
            return subprocess.check_output(
                cmd, 
                shell=True,
                stderr=subprocess.DEVNULL,
                universal_newlines=True
            ).strip()
        except subprocess.CalledProcessError:
            return None

    @staticmethod
    def match_version(version_str: str, pattern: str) -> Optional[str]:
        """
        使用正则表达式提取版本号
        参数:
            version_str - 原始版本字符串，如 "Ubuntu 22.04.3 LTS"
            pattern - 正则表达式，如 r"(\d+\.\d+)"
        返回: 匹配的版本号 (如 "22.04")，未匹配返回 None
        """
        match = re.search(pattern, version_str)
        return match.group(1) if match else None

# ---------------------------------------------------------------------
# 示例：如何为特定系统编写检测类
# 开发者应删除此示例并创建自己的子类
# ---------------------------------------------------------------------

class ExampleOSDetector(BaseOSDetector):
    """示例：检测虚构的 "ExampleOS" 系统"""
    
    def detect(self) -> bool:
        # 方法 1: 检查标识文件
        if self.check_file_exists("/etc/exampleos-release"):
            return True
        
        # 方法 2: 解析 os-release 信息
        os_info = self.get_os_release()
        if os_info.get("ID", "") == "exampleos":
            return True
        
        # 方法 3: 执行命令检测
        version_output = self.exec_command("exampleos-version")
        if version_output and "ExampleOS" in version_output:
            return True
            
        return False

    def get_version(self) -> Optional[str]:
        """扩展方法：获取 ExampleOS 的详细版本"""
        os_info = self.get_os_release()
        if "VERSION_ID" in os_info:
            return self.match_version(os_info["VERSION_ID"], r"(\d+\.\d+)")
        return None

# 使用示例
if __name__ == "__main__":
    detector = ExampleOSDetector()
    if detector.detect():
        print(f"检测到 ExampleOS 系统，版本: {detector.get_version()}")
    else:
        print("未检测到 ExampleOS")